#!c:\Python27\python.exe

#import Imagenes as im
import cv2.cv as cv
import math as ma
import loggear as lg

def distanciaMax(lista):
    l = list(lista)
    x = 0
    y = 0
    while l:
        ptoX, ptoY = l.pop()
        if ptoX > x:
            x = ptoX
        if ptoY > y:
            y = ptoY
    return x + 30, y + 30

def armarImagen(lista):
    l = list(lista)
    alto, ancho = distanciaMax(l)
    img = cv.CreateImage((alto, ancho), cv.IPL_DEPTH_8U, 1)
    cv.Zero(img)
    while l:
        pto = l.pop()
        #cv.Rectangle(img, pto, pto, 255)
        #cv.Circle(img, pto, 4, 255, 1)
        cv.Circle(img, pto, 2, 255, 5)
    return img

def distanciaEnX(pto1, pto2):
    x1, _ = pto1
    x2, _ = pto2
    return cmp(x1, x2)

def distanciaEnY(pto1, pto2):
    _, y1 = pto1
    _, y2 = pto2
    return cmp(y1, y2)
    
def ordenar(lista, fn):
    l = list(lista)
    l.sort(fn)
    return l
       
def identificarLineasH(lista, radio):
    puntos = list(lista)
    puntos = ordenar(puntos, distanciaEnY)
    puntos.reverse()
    lineas = []
    anterior = 0
    
    while puntos:
        _, y = puntos.pop()
        while y - anterior > radio:
            lineas.append(anterior)
            anterior += 1
        anterior = y + radio
        lineas.sort()
        #BORRAR DUPLICADOS
    return lineas

def complementarFranjas(franjas):
    aux = list(franjas)
    complemento = []
    aux = ordenar(aux, distanciaEnX)
    aux.reverse()
    #max_franja = 0
    min_franja = 0
    while aux:
        x1, x2 = aux.pop()
        complemento.append([min_franja, x1])
        min_franja = x2
    return complemento

#def rotarPuntos(listaPuntos, angulo):
#    ptos = list(listaPuntos)
#    ang = ma.radians(angulo)
#    ang = ang * (-1)
#    ptosR = []
#    while ptos:
#        x, y = ptos.pop()
#        #xR = ma.trunc(ma.cos(ang) * x - ma.sin(ang) * y)
#        #yR = ma.trunc(ma.sin(ang) * x + ma.cos(ang) * y)
#        xR = redondear(ma.cos(ang) * x - ma.sin(ang) * y)
#        yR = redondear(ma.sin(ang) * x + ma.cos(ang) * y)
#        pto = (xR, yR)
#        ptosR.append(pto)
#    return ptosR

def existePtoEn(puntos, rangoX, rangoY):
    x1, x2 = rangoX
    y1, y2 = rangoY
    ptos = list(puntos)
    while ptos:
        pto = ptos.pop()
        x, y = pto
        if x1 <= x <= x2:
            if y1 <= y <= y2:
                puntos.remove(pto)
                return 1
    return 0

def filtrarPtosEnFranja(puntos, (y1, y2)):
    ptos = list(puntos)
    puntos = []
    while ptos:
        x, y = ptos.pop()
        if y1 <= y <= y2:
            puntos.append((x, y))
    return puntos

def filtrarPtos(puntos, (y1, y2)):
    ptos = list(puntos)
    ptosX = []
    ptosY = []
    while ptos:
        x, y = ptos.pop()
        if y <= y2:
            if y >= y1:
                ptosX.append(x)
                ptosY.append(y)
    return ptosX, ptosY

#def minimos_cuadrados(x, y):
#    m = len(x) #mido la longitud de la lista x
#    if m > 5:
#        sumax = 0.0
#        sumay = 0.0
#        sumaxy = 0.0
#        sumaxx = 0.0
#        for i in range(m):
#            sumax += x[i]
#            sumay += y[i]
#            sumaxy += x[i] * y[i]
#            sumaxx += x[i] * x[i]
#        denom = (m * sumaxx - sumax * sumax)
#        if denom <> 0:
#            pendiente = (m * sumaxy - sumax * sumay) / denom
#            ordenada = (sumaxx * sumay - sumax * sumaxy) / denom
#            return pendiente, ordenada
#    return 0, 0

#def calcularAngulo(puntos, limites):
#    ptosX, ptosY = filtrarPtos(puntos, limites)
#    pend, _ = minimos_cuadrados(ptosX, ptosY)
#    angRad = ma.atan(pend)
#    angulo = ma.degrees(angRad)
#    return angulo

#def percentiles(N, percent, key=lambda x:x):
#    if not N:
#        return 0
#    N = sorted(N)
#    k = (len(N) - 1) * percent
#    f = ma.floor(k)
#    c = ma.ceil(k)
#    if f == c:
#        return key(N[int(k)])
#    d0 = key(N[int(f)]) * (c - k)
#    d1 = key(N[int(c)]) * (k - f)
#    return d0 + d1
    
#def calcAngProm(franjaH, puntos):
#    lineas = list(franjaH)
#    #lineas.reverse()
#    #angulo = 0
#    lista = []
#    while lineas:
#        limites = lineas.pop()
#        angulo = calcularAngulo(puntos, limites)
#        #print angulo
#        if angulo <> 0:
#            lista.append(angulo)
#    if lista:
#        #return percentiles(lista, 0.5)
#        return sum(lista) / len(lista)
#    return 0

#def promLista(lista):
#    #numeros = list(lista)
#    numeros = lista
#    suma = 0
#    cant = 0
#    prom = 0
#    
#    while numeros:
#        suma += numeros.pop()
#        cant += 1
#    if cant > 0:
#        prom = suma / cant
#    return ma.trunc(prom)

def promListaEstricto(lista):
    numeros = list(lista)
    
    suma = 0
    cant = 0
    prom = 0
    
    while numeros:
        suma += numeros.pop()
        cant += 1
    if cant > 0:
        prom = suma / cant
    suma = 0
    cant = 0
    numeros = lista
    while numeros:
        num = numeros.pop()        
        if prom / 1.2 < num < prom * 1.2:
            suma += num
            cant += 1 
    if cant > 0:
        prom = suma / cant         
    return ma.trunc(prom)

#def redondear(x):
#    decim, _ = ma.modf(x)
#    if decim > 0.5:
#        return ma.trunc(ma.ceil(x))
#    else:
#        return ma.trunc(ma.floor(x))

def leerCaracter(linea, columna, franjaH, franjaV, puntos):
    try:
        p1 = existePtoEn(puntos, franjaV[columna], franjaH[linea])
    except:
        p1 = 0
    try:
        p2 = existePtoEn(puntos, franjaV[columna], franjaH[linea + 1])
    except:
        p2 = 0
    try:
        p3 = existePtoEn(puntos, franjaV[columna], franjaH[linea + 2])
    except:
        p3 = 0
    try:
        p4 = existePtoEn(puntos, franjaV[columna + 1], franjaH[linea])
    except:
        p4 = 0
    try:
        p5 = existePtoEn(puntos, franjaV[columna + 1], franjaH[linea + 1])
    except:
        p5 = 0
    try:
        p6 = existePtoEn(puntos, franjaV[columna + 1], franjaH[linea + 2])
    except:
        p6 = 0
    
    c = p1 + 2 * p2 + 4 * p3 + 8 * p4 + 16 * p5 + 32 * p6

    return c

def histogramaPuntos(puntos, radio):
    ptos = list(puntos)
    maxX, maxY = distanciaMax(puntos)
    lHistX = []
    for i in range(0, maxX):
        lHistX.append(0)
    lHistY = []
    for i in range(0, maxY):
        lHistY.append(0)
    
    mX = mY = 0
    
    while ptos:
        x, y = ptos.pop()
        lHistX[x] = lHistX[x] + 100
        if lHistX[x] > mX:
            mX = lHistX[x]
        lHistY[y] = lHistY[y] + 100
        if lHistY[y] > mY:
            mY = lHistY[y]
            
    franjaY = [] #H
    franjaX = [] #V
    
    imgHistX = cv.CreateImage((maxX, mX), 8, 1)
    cv.Rectangle(imgHistX, (0, 0), (maxX, mX), 255, -1)
    imgHistY = cv.CreateImage((maxY, mY), 8, 1)
    cv.Rectangle(imgHistY, (0, 0), (maxY, mY), 255, -1)

    inicio = fin = 0    
    radioX = radio - 4
    for i in range(0, maxX - 1):
        if lg.hayLog():
            cv.Rectangle(imgHistX, (i - radioX, mX), (i + radioX, mX - lHistX[i]), 0, -1)
            #cv.Line(imgHistX, (i, mX), (i, mX - lHistX[i]), 0)
        if lHistX[i]:
            if i - radioX > fin:
                franjaX.append((inicio, fin))
                inicio = i - radioX
            fin = i + radioX
    franjaX.append((inicio, fin))
    fin += radioX
    franjaX.append((fin, fin))
    lg.loggear('HistogramaX', imgHistX)
    
    inicio = fin = 0    
    for i in range(0, maxY - 1):
        if lg.hayLog():
            cv.Rectangle(imgHistY, (i - radio, mY), (i + radio, mY - lHistY[i]), 0, -1)
            #cv.Line(imgHistY, (i, mY), (i, mY - lHistY[i]), 0)
        if lHistY[i]:
            if i - radio > fin:
                franjaY.append((inicio, fin))
                inicio = i - radio
            fin = i + radio
    franjaY.append((inicio, fin))
    fin += radio
    franjaY.append((fin, fin))
    lg.loggear('HistogramaY', imgHistY)
        
    return franjaY, franjaX
    
def dividirFranjas(franjas, cant):
    franjaOut = []
    franjas.reverse()
    
    if cant == 0:
        return franjas
    while franjas:
        pto1, pto2 = franjas.pop()
        tamanio = (pto2 - pto1) / cant
        i = 0
        if tamanio == 0:
            franjaOut.append((pto1, pto2))
        else:
            while i < cant:
                pto2 = pto1 + tamanio - 1
                franjaOut.append((pto1, pto2))
                pto1 = pto2 + 2
                i += 1
    return franjaOut

def agregarFranjas(franjas):
    tamanioPuntos = []
    tamanioSeparacion = []
    franjasCompletas = []
    franjasAux = list(franjas)
    
    franjasAux.reverse()
    
    ant = 0
    while franjasAux:
        pto1, pto2 = franjasAux.pop()
        if ant == 0:
            pass
        else:
            tamanioPuntos.append(pto2 - pto1)
            tamanioSeparacion.append(pto1 - ant)
        ant = pto2
    ptos = promListaEstricto(tamanioPuntos)
    sepa = promListaEstricto(tamanioSeparacion)
    
    #print ptos
    #print sepa
    franjasAux = list(franjas)

    franjasAux.reverse()
    margen = 1.15
    ant = 0
    while franjasAux:
        pto1, pto2 = franjasAux.pop()
        #print '(' + str(pto1) + ',' + str(pto2) + ')\t\t' + str(ant)
        if ant == 0:
            pass
        elif pto1 - ant >= ptos + sepa:
            franjasAux.append((pto1, pto2))
            pto1 = ant + sepa
            pto2 = pto1 + ptos
        elif not (ptos / margen <= pto2 - pto1 <= ptos * margen):
            if franjasAux:
                pto1B, pto2B = franjasAux.pop()
            else:
                pto2B = pto1 + ptos
            if (pto2B - pto1 > ptos * margen):
                franjasAux.append((pto1B, pto2B))
                pto2 = pto1 + ptos
            elif (pto2B - pto1 < ptos / margen):
                if franjasAux:
                    pto1C, pto2C = franjasAux.pop()
                else:
                    pto2C = pto1 + ptos
                if (pto2C - pto1 > ptos * margen):
                    franjasAux.append((pto1C, pto2B))
                    pto2 = pto1 + ptos
                elif (pto2C - pto1 < ptos / margen):
                    pto2 = pto1 + ptos
                else:
                    pto2 = pto2C                
            else:
                pto2 = pto2B
#        elif not (ptos / margen <= pto2 - pto1 <= ptos * margen):
#            pto1 = ant + sepa
#            pto2 = ant + sepa + ptos            
        franjasCompletas.append((pto1, pto2))
        ant = pto2
            
    franjasCompletas.append((pto2 + sepa, pto2 + sepa))
    return franjasCompletas

def obtenerFranjas(puntos, radio):
    franjaHAux, franjaVAux = histogramaPuntos(puntos, radio)
#    print franjaHAux
    franjaHAux = agregarFranjas(franjaHAux)
    franjaVAux = agregarFranjas(franjaVAux)
#    print '------'
#    print franjaHAux
    franjaH = dividirFranjas(franjaHAux, 3)
    franjaV = dividirFranjas(franjaVAux, 2)
   
    return franjaH, franjaV
#    return franjaHAux, franjaVAux

#def obtenerFranjasGruesas(puntos, radio, anchoImagen, altoImagen):
#    franjaHAux, franjaVAux = histogramaPuntos(puntos, radio)
#    franjaH = agregarFranjas(franjaHAux, altoImagen)
#    franjaV = agregarFranjas(franjaVAux, anchoImagen)
#        
#    return franjaH, franjaV

#def obtenerPtoInicial(puntos):
#    franjaY, franjaX = histogramaPuntos(puntos, 5)      
#    ptoY, _ = franjaY[1]    
#    ptoX, _ = franjaX[1]    
#    return (ptoX, ptoY)
